home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / fscheck / RCS / fsUtils.c,v < prev    next >
Encoding:
Text File  |  1992-06-10  |  41.6 KB  |  1,733 lines

  1. head     1.10;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.10
  10. date     92.06.09.21.48.15;  author jhh;  state Exp;
  11. branches ;
  12. next     1.9;
  13.  
  14. 1.9
  15. date     90.11.01.23.28.38;  author jhh;  state Exp;
  16. branches ;
  17. next     1.8;
  18.  
  19. 1.8
  20. date     90.10.10.15.29.09;  author mendel;  state Exp;
  21. branches ;
  22. next     1.7;
  23.  
  24. 1.7
  25. date     90.10.10.11.22.15;  author jhh;  state Exp;
  26. branches ;
  27. next     1.6;
  28.  
  29. 1.6
  30. date     90.05.01.15.36.47;  author jhh;  state Exp;
  31. branches ;
  32. next     1.5;
  33.  
  34. 1.5
  35. date     90.02.14.15.55.33;  author jhh;  state Exp;
  36. branches ;
  37. next     1.4;
  38.  
  39. 1.4
  40. date     89.10.03.17.47.50;  author jhh;  state Exp;
  41. branches ;
  42. next     1.3;
  43.  
  44. 1.3
  45. date     89.09.25.16.41.21;  author jhh;  state Exp;
  46. branches ;
  47. next     1.2;
  48.  
  49. 1.2
  50. date     89.06.21.23.56.14;  author jhh;  state Exp;
  51. branches ;
  52. next     1.1;
  53.  
  54. 1.1
  55. date     89.02.28.12.23.51;  author jhh;  state Exp;
  56. branches ;
  57. next     ;
  58.  
  59.  
  60. desc
  61. @utility procedures for fscheck
  62. @
  63.  
  64.  
  65. 1.10
  66. log
  67. @get host name from gethostname
  68. @
  69. text
  70. @/* 
  71.  * fsUtils.c --
  72.  *
  73.  *    Utility procedures for fscheck
  74.  *
  75.  * Copyright 1989 Regents of the University of California
  76.  * Permission to use, copy, modify, and distribute this
  77.  * software and its documentation for any purpose and without
  78.  * fee is hereby granted, provided that the above copyright
  79.  * notice appear in all copies.  The University of California
  80.  * makes no representations about the suitability of this
  81.  * software for any purpose.  It is provided "as is" without
  82.  * express or implied warranty.
  83.  */
  84.  
  85. #ifndef lint
  86. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fsUtils.c,v 1.9 90/11/01 23:28:38 jhh Exp $ SPRITE (Berkeley)";
  87. #endif /* not lint */
  88.  
  89. #include "option.h"
  90. #include "list.h"
  91. #include "fscheck.h"
  92. #include <string.h>
  93. #include <host.h>
  94. #include <sys/file.h>
  95. #include <sys/stat.h>
  96. #include <stdio.h>
  97. #include <sysStats.h>
  98. #include <sys/param.h>
  99.  
  100. void WriteOutputFile();
  101. int CloseOutputFile();
  102.  
  103. FILE outputFileInfo;
  104. FILE *outputFile = &outputFileInfo;
  105.  
  106.  
  107.  
  108. /*
  109.  *----------------------------------------------------------------------
  110.  *
  111. * ReadFileDescBitmap --
  112.  *
  113.  *    Read in the file descriptor bitmap.
  114.  *
  115.  * Results:
  116.  *    A pointer to the file descriptor bit map.
  117.  *
  118.  * Side effects:
  119.  *    Memory allocated for the bit map.
  120.  *
  121.  *----------------------------------------------------------------------
  122.  */
  123. unsigned char *
  124. ReadFileDescBitmap(partFID, domainPtr)
  125.     register Ofs_DomainHeader *domainPtr;    /* Ptr to domain to read bitmap for. */
  126. {
  127.     register unsigned char *bitmap;
  128.  
  129.     /*
  130.      * Allocate the bitmap.
  131.      */
  132.     AllocByte(bitmap,unsigned char,domainPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
  133.     if (tooBig) {
  134.     Output(stderr,"CheckFileSystem: Heap limit too small.\n");
  135.     exit(EXIT_MORE_MEMORY);
  136.     }
  137.     if (Disk_BlockRead(partFID, domainPtr, domainPtr->fdBitmapOffset,
  138.           domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  139.     OutputPerror("ReadFileDescBitmap: Read failed");
  140.     exit(EXIT_READ_FAILURE);
  141.     }
  142.     return(bitmap);
  143. }
  144.  
  145.  
  146. /*
  147.  *----------------------------------------------------------------------
  148.  *
  149.  * WriteFileDescBitmap --
  150.  *
  151.  *    Write out the file descriptor bitmap.
  152.  *
  153.  * Results:
  154.  *    None.
  155.  *
  156.  * Side effects:
  157.  *    None.
  158.  *
  159.  *----------------------------------------------------------------------
  160.  */
  161. void
  162. WriteFileDescBitmap(partFID, domainPtr, bitmap)
  163.     int                partFID;    /* Raw handle on disk. */
  164.     register Ofs_DomainHeader     *domainPtr;    /* Domain to write bitmap for.*/
  165.     register unsigned char     *bitmap;    /* Bitmap to write. */
  166. {
  167.     if (Disk_BlockWrite(partFID, domainPtr, domainPtr->fdBitmapOffset,
  168.            domainPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  169.     OutputPerror("WriteFileDescBitmap: Write failed");
  170.     exit(EXIT_WRITE_FAILURE);
  171.     }
  172. }
  173.  
  174.  
  175. /*
  176.  *----------------------------------------------------------------------
  177.  *
  178.  * ReadBitmap --
  179.  *
  180.  *    Read the bitmap off disk.
  181.  *
  182.  * Results:
  183.  *    A pointer to the bitmap.
  184.  *
  185.  * Side effects:
  186.  *    Memory allocated for the bit map.
  187.  *
  188.  *----------------------------------------------------------------------
  189.  */
  190. unsigned char *
  191. ReadBitmap(partFID, domainPtr)
  192.     int                partFID;    /* Raw disk handle. */
  193.     register Ofs_DomainHeader    *domainPtr;    /* Domain to read. */
  194. {
  195.     unsigned char *bitmap;
  196.     AllocByte(bitmap,unsigned char,domainPtr->bitmapBlocks * FS_BLOCK_SIZE);
  197.     if (tooBig) {
  198.     Output(stderr,"CheckFileSystem: Heap limit too small.\n");
  199.     exit(EXIT_MORE_MEMORY);
  200.     }
  201.     if (Disk_BlockRead(partFID, domainPtr, domainPtr->bitmapOffset,
  202.           domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
  203.     OutputPerror("ReadBitmap: Read failed");
  204.     exit(EXIT_READ_FAILURE);
  205.     }
  206.     return(bitmap);
  207. }
  208.  
  209.  
  210. /*
  211.  *----------------------------------------------------------------------
  212.  *
  213.  * WriteBitmap --
  214.  *
  215.  *    Write the bitmap to disk.
  216.  *
  217.  * Results:
  218.  *    None.
  219.  *
  220.  * Side effects:
  221.  *    None.
  222.  *
  223.  *----------------------------------------------------------------------
  224.  */
  225. void
  226. WriteBitmap(partFID, domainPtr, bitmap)
  227.     int                partFID;    /* Raw handle for disk. */
  228.     register Ofs_DomainHeader    *domainPtr;    /* Domain to write. */
  229.     unsigned char        *bitmap;    /* Bitmap to write. */
  230. {
  231.     if (Disk_BlockWrite(partFID, domainPtr, domainPtr->bitmapOffset,
  232.            domainPtr->bitmapBlocks, (Address) bitmap) < 0) {
  233.     OutputPerror("WriteBitmap: Write failed");
  234.     exit(EXIT_WRITE_FAILURE);
  235.     }
  236. }
  237.  
  238.  
  239. /*
  240.  *----------------------------------------------------------------------
  241.  *
  242.  * WriteFileDesc --
  243.  *
  244.  *    Write the file descriptors to disk.
  245.  *
  246.  * Results:
  247.  *    None.
  248.  *
  249.  * Side effects:
  250.  *    File descriptors on the modified list are all written to disk.
  251.  *
  252.  *----------------------------------------------------------------------
  253.  */
  254. void
  255. WriteFileDesc(partFID, domainPtr, listPtr, descInfoPtr)
  256.     int             partFID;    /* Raw handle for disk. */
  257.     register Ofs_DomainHeader     *domainPtr;    /* Domain to write to. */
  258.     List_Links            *listPtr;    /* Pointer to list of modified
  259.                          * file descriptors to write
  260.                          * out. */
  261.     FdInfo            *descInfoPtr;    /* Pointer to info about all
  262.                          * of the descriptors. */
  263.                     
  264. {
  265.     char        block[FS_BLOCK_SIZE];
  266.     int            blockNum;
  267.     int            offset;
  268.     ModListElement    *modElemPtr;
  269.     int            badBlock;
  270.  
  271.     LIST_FORALL(listPtr, (List_Links *)modElemPtr) {
  272.     badBlock = 0;
  273.     blockNum = domainPtr->fileDescOffset + 
  274.             modElemPtr->fdNum / FSDM_FILE_DESC_PER_BLOCK;
  275.     offset = (modElemPtr->fdNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) *
  276.             FSDM_MAX_FILE_DESC_SIZE;
  277.     /*
  278.      * Try to read the whole block at once unless we already know it's
  279.      * bad.  Read it a sector at a time if we hit an error earlier
  280.      * or if we get one now.
  281.      */
  282.     if ((descInfoPtr[modElemPtr->fdNum].flags &
  283.          (FD_RELOCATE|FD_UNREADABLE)) == 0) {
  284.         if (Disk_BlockRead(partFID, domainPtr, blockNum, 1,
  285.                    (Address) block) < 0) {
  286.         OutputPerror("WriteFileDesc: Warning: read failed");
  287.         badBlock = 1;
  288.         }
  289.     } else {
  290.         badBlock = 1;
  291.     }
  292.     if (badBlock) {
  293.         (void) Disk_BadBlockRead(partFID, domainPtr, blockNum,
  294.                      (Address) block);
  295.     }
  296.     bcopy((Address) modElemPtr->fdPtr, (Address) &block[offset],
  297.           sizeof(Fsdm_FileDescriptor));
  298.     if (Disk_BlockWrite(partFID, domainPtr, blockNum, 1,
  299.                (Address) block) < 0) {
  300.         OutputPerror("WriteFileDesc: Write failed");
  301.         exit(EXIT_WRITE_FAILURE);
  302.     }
  303.     }
  304. }
  305.  
  306.  
  307. /*
  308.  *----------------------------------------------------------------------
  309.  *
  310.  * WriteSummaryInfo --
  311.  *
  312.  *    Update summary information on disk.
  313.  *
  314.  * Results:
  315.  *    None.
  316.  *
  317.  * Side effects:
  318.  *    None.
  319.  *
  320.  *----------------------------------------------------------------------
  321.  */
  322. void
  323. WriteSummaryInfo(partFID, labelPtr, domainPtr, numKblocks, numFiles)
  324.     int            partFID;    /* Handle on raw disk */
  325.     Disk_Label        *labelPtr;    /* The disk label. */
  326.     Ofs_DomainHeader    *domainPtr;    /* Reference to domain header to
  327.                      * fill in */
  328.     int            numKblocks;    /* Number of 1 Kbyte blocks. */
  329.     int            numFiles;    /* Number of files. */
  330. {
  331.     Ofs_SummaryInfo    *summaryInfoPtr;
  332.     int         status;
  333.  
  334.     summaryInfoPtr = Disk_ReadSummaryInfo(partFID, labelPtr);
  335.     if (summaryInfoPtr == NULL) {
  336.     OutputPerror("WriteSummaryInfo: Read failed");
  337.     exit(EXIT_READ_FAILURE);
  338.     }
  339.     summaryInfoPtr->numFreeFileDesc = domainPtr->numFileDesc - numFiles -
  340.         numBadDesc;
  341.     summaryInfoPtr->numFreeKbytes = 
  342.         domainPtr->dataBlocks * FS_FRAGMENTS_PER_BLOCK - numKblocks;
  343.     if (clearDomainNumber) {
  344.     Output(stderr,"Clearing domain number field.\n");
  345.     summaryInfoPtr->domainNumber = -1;
  346.     }
  347.     /*
  348.      * Do not set the checked bit if there is a hard error, or if we ran
  349.      * out of memory or if the setCheckedBit flag is not set.
  350.      */
  351.     if (! (errorType < 0 || errorType == EXIT_OUT_OF_MEMORY || 
  352.        !setCheckedBit)) {
  353.     if (verbose) {
  354.         Output(stderr,
  355.         "Setting OFS_DOMAIN_JUST_CHECKED bit in summary sector.\n");
  356.     }
  357.     summaryInfoPtr->flags |= OFS_DOMAIN_JUST_CHECKED;
  358.     }
  359.     summaryInfoPtr->fixCount = fixCount;
  360.     status = Disk_WriteSummaryInfo(partFID, labelPtr, summaryInfoPtr);
  361.     if (status < 0) {
  362.     OutputPerror("WriteSummaryInfo: Write failed");
  363.     exit(EXIT_WRITE_FAILURE);
  364.     }
  365.     free((char *) summaryInfoPtr);
  366. }
  367.  
  368.  
  369. /*
  370.  *----------------------------------------------------------------------
  371.  *
  372.  * RecoveryCheck --
  373.  *
  374.  *    See if the disk was just checked. Print out information
  375.  *    from summary sector.
  376.  *
  377.  * Results:
  378.  *    Return 1 if the disk was just checked, 0 otherwise.
  379.  *
  380.  * Side effects:
  381.  *    fixCount is set to the value in the summary sector.
  382.  *
  383.  *----------------------------------------------------------------------
  384.  */
  385. int
  386. RecoveryCheck(partFID, labelPtr)
  387.     int            partFID;    /* Handle on raw disk */
  388.     Disk_Label        *labelPtr;    /* The disk label. */
  389. {
  390.     Ofs_SummaryInfo        *summaryInfoPtr;
  391.     int                i;
  392.     ReturnStatus        status = SUCCESS;
  393.     char                name[MAXHOSTNAMELEN];
  394.  
  395.     summaryInfoPtr = Disk_ReadSummaryInfo(partFID, labelPtr);
  396.     if (summaryInfoPtr == NULL) {
  397.     OutputPerror("RecoveryCheck: Summary sector read failed.\n");
  398.     exit(EXIT_READ_FAILURE);
  399.     }
  400.     fixCount = summaryInfoPtr->fixCount;
  401.     if (verbose) {
  402.     Output(stderr, "Summary Sector Info:\n");
  403.     Output(stderr, "%s domain %d %s\n", summaryInfoPtr->domainPrefix,
  404.            summaryInfoPtr->domainNumber, 
  405.            (summaryInfoPtr->flags & OFS_DOMAIN_NOT_SAFE) ? "not-safe" : 
  406.            "safe");
  407.         if (summaryInfoPtr->flags & OFS_DOMAIN_TIMES_VALID) {
  408.         Output(stderr, "Down %d seconds.\n",summaryInfoPtr->attachSeconds -
  409.            summaryInfoPtr->detachSeconds);
  410.         } else {
  411.         Output(stderr, "Attach/Detach fields not valid.\n");
  412.     }
  413.     Output(stderr, "Fscheck has fixed disk %d times already.\n", fixCount);
  414.     } else { 
  415.     Output(stderr, "\"%s\"\n", summaryInfoPtr->domainPrefix);
  416.     }
  417.     gethostname(name, MAXHOSTNAMELEN);
  418.     /*
  419.      * Check and see if the disk is already attached.  
  420.      */
  421.     for (i = 0; status == SUCCESS; i++) {
  422.     Fs_Prefix            prefix;
  423.     Host_Entry             *serverInfoPtr;
  424.  
  425.     bzero((char *) &prefix, sizeof(Fs_Prefix));
  426.     status = Sys_Stats(SYS_FS_PREFIX_STATS, i, (Address) &prefix);
  427.     if (status == SUCCESS) {
  428.         if (!strcmp(prefix.prefix, summaryInfoPtr->domainPrefix)) {
  429.         serverInfoPtr = Host_ByID(prefix.serverID);
  430.         if (serverInfoPtr == NULL) {
  431.             continue;
  432.         }
  433.         if (!strcmp(serverInfoPtr->name, name)) {
  434.             if (verbose) {
  435.             Output(stderr, "Disk is already attached\n");
  436.             }
  437.             attached = TRUE;
  438.             break;
  439.         }
  440.         }
  441.     }
  442.     }
  443.     if (clearFixCount) {
  444.     if (!silent) {
  445.         Output(stderr, "Fix count being reset to 0.\n");
  446.     }
  447.     fixCount = 0;
  448.     }
  449.     return(summaryInfoPtr->flags & OFS_DOMAIN_JUST_CHECKED);
  450. }
  451.  
  452.  
  453.  
  454. /*
  455.  *----------------------------------------------------------------------
  456.  *
  457.  * CheckFDBitmap --
  458.  *
  459.  *    Scan through the file descriptors and determine if all file 
  460.  *    descriptors marked as allocated and free in the bit map are
  461.  *    really that way.
  462.  *
  463.  * Results:
  464.  *    None.
  465.  *
  466.  * Side effects:
  467.  *    None.
  468.  *
  469.  *----------------------------------------------------------------------
  470.  */
  471.  
  472. void
  473. CheckFDBitmap(domainPtr, fdNum, block, bitmapPtrPtr)
  474.     register    Ofs_DomainHeader     *domainPtr;        /* Domain to check. */
  475.     int                 fdNum;            /* File descriptor to
  476.                              * check. */
  477.     Address             block;            /* Disk block that
  478.                              * FD is in. */
  479.     register    unsigned char      **bitmapPtrPtr;    /* Ptr to FD bitmap
  480.                              * entry for fdNum. */
  481. {
  482.     int                i, j;
  483.     register unsigned char     *bitmaskPtr;
  484.     int                   allocated;
  485.     Fsdm_FileDescriptor        *fdPtr;
  486.  
  487.     for (i = 0; 
  488.      i < FSDM_FILE_DESC_PER_BLOCK / BITS_PER_BYTE && 
  489.         fdNum < domainPtr->numFileDesc;
  490.      i++, (*bitmapPtrPtr)++){
  491.     for (j = 0, bitmaskPtr = bitmasks; 
  492.          j < BITS_PER_BYTE && fdNum < domainPtr->numFileDesc; 
  493.          j++, fdNum++, bitmaskPtr++) {
  494.  
  495.         fdPtr = (Fsdm_FileDescriptor *)&block[(i * BITS_PER_BYTE + j) * FSDM_MAX_FILE_DESC_SIZE];
  496.         allocated = **bitmapPtrPtr & *bitmaskPtr;
  497.         if (allocated && (fdPtr->flags & FSDM_FD_FREE)) {
  498.         if (bitmapVerbose) {
  499.             Output(stderr,
  500.        "Free file descriptor %d allocated in bitmap.  Bitmap corrected.\n",
  501.                    fdNum);
  502.         }
  503.         foundError = 1;
  504.         fdBitmapError = 1;
  505.         **bitmapPtrPtr &= ~*bitmaskPtr;
  506.         } else if (!allocated && !(fdPtr->flags & FSDM_FD_FREE)) {
  507.         if (bitmapVerbose) {
  508.             Output(stderr,
  509.        "Allocated file descriptor %d free in bitmap.  Bitmap corrected.\n",
  510.                    fdNum);
  511.         }
  512.         foundError = 1;
  513.         fdBitmapError = 1;
  514.         **bitmapPtrPtr |= *bitmaskPtr;
  515.         }
  516.     }
  517.     }
  518. }
  519.  
  520.  
  521. /*
  522.  *----------------------------------------------------------------------
  523.  *
  524.  * SetBadDescBitmap --
  525.  *
  526.  *    Go through the bitmaps and flag all the bits for this block as
  527.  *    allocated.
  528.  *
  529.  * Results:
  530.  *    None.
  531.  *
  532.  * Side effects:
  533.  *    None.
  534.  *
  535.  *----------------------------------------------------------------------
  536.  */
  537. void
  538. SetBadDescBitmap(domainPtr, fdNum, bitmapPtrPtr)
  539.     register    Ofs_DomainHeader     *domainPtr;        /* Domain to fix. */
  540.     int                 fdNum;            /* Bad file desc. */
  541.     register    unsigned char      **bitmapPtrPtr;    /* Ptr to bitmap entry
  542.                              * for bad file desc.*/
  543. {
  544.     int                i, j;
  545.     register unsigned char     *bitmaskPtr;
  546.  
  547.     for (i = 0; i < FSDM_FILE_DESC_PER_BLOCK / BITS_PER_BYTE && 
  548.         fdNum < domainPtr->numFileDesc;
  549.          i++, (*bitmapPtrPtr)++){
  550.     for (j = 0, bitmaskPtr = bitmasks; 
  551.          j < BITS_PER_BYTE && fdNum < domainPtr->numFileDesc; 
  552.          j++, fdNum++, bitmaskPtr++) {
  553.  
  554.          **bitmapPtrPtr |= *bitmaskPtr;
  555.      }
  556.     }
  557. }
  558.  
  559. /*
  560.  *----------------------------------------------------------------------
  561.  *
  562.  * MarkBitmap --
  563.  *
  564.  *    Mark the bits in the bit map.
  565.  *    update the cylinder map to reflect which blocks are allocated.
  566.  *
  567.  * Results:
  568.  *    -1 if couldn't mark the bitmap, 0 otherwise.
  569.  *
  570.  * Side effects:
  571.  *    None.
  572.  *
  573.  *----------------------------------------------------------------------
  574.  */
  575. int
  576. MarkBitmap(fdNum, blockNum, bitmapPtr, numFrags, domainPtr)
  577.     int          fdNum;
  578.     int          blockNum;
  579.     unsigned char *bitmapPtr;
  580.     int          numFrags;
  581.     Ofs_DomainHeader  *domainPtr;
  582. {
  583.     register    unsigned char     *bytePtr;
  584.     register    unsigned char     *bitmaskPtr;
  585.     unsigned     char              bitmask;
  586.     int                i;
  587.     int                fullBlockNum;
  588.     int                fragOffset;
  589.     int                dupBlocks;
  590.  
  591.     if (blockNum >= num1KBlocks || blockNum < 0) {
  592.     if (verbose || lastErrorFD != fdNum) {
  593.         Output(stderr, "Block pointer %d invalid in file %d\n", 
  594.                blockNum, fdNum);
  595.         lastErrorFD = fdNum;
  596.     }
  597.     foundError = 1;
  598.     return(-1);
  599.     }
  600.     bitmask = 0;
  601.     fullBlockNum = blockNum / FS_FRAGMENTS_PER_BLOCK;
  602.     bytePtr = GetBitmapPtr(domainPtr, bitmapPtr, fullBlockNum);
  603.     fragOffset = blockNum & 0x3;
  604.     if ((fullBlockNum % domainPtr->geometry.blocksPerCylinder) & 0x1) {
  605.     fragOffset += 4;
  606.     }
  607.     bitmaskPtr = &bitmasks[fragOffset];
  608.  
  609.     dupBlocks = 0;
  610.     for (i = 0; i < numFrags; i++, bitmaskPtr++) {
  611.     if (*bitmaskPtr & *bytePtr || 
  612.         (fdNum != FSDM_ROOT_FILE_NUMBER) && blockNum == 0) { 
  613.         if (noCopy) {
  614.         if (verbose || lastErrorFD != fdNum) {
  615.             Output(stderr,
  616.     "File %d references previously allocated block.  Block %d deleted.\n", 
  617.                fdNum, blockNum + i);
  618.             lastErrorFD = fdNum;
  619.         }
  620.         foundError = 1;
  621.         return -1;
  622.         }
  623.         dupBlocks++;
  624.     }
  625.     bitmask |= *bitmaskPtr;
  626.     }
  627.     if (dupBlocks > 0) {
  628.     foundError = 1;
  629.     /*
  630.      * All fragments are duplicates, so mark bitmap and return 1 so that
  631.      * these fragments are copied.
  632.      */
  633.     if (verbose || lastErrorFD != fdNum) {
  634.         Output(stderr,"File %d contains duplicate block %d.\n",fdNum,
  635.            blockNum);
  636.     }
  637.     *bytePtr |= bitmask;
  638.     return(1);
  639.     }
  640.     *bytePtr |= bitmask;
  641.     return(0);
  642. }
  643.  
  644. /*
  645.  *----------------------------------------------------------------------
  646.  *
  647.  * Output ---
  648.  *    
  649.  *    Prints the output to the given stream, and if the outputFile is  
  650.  *    not NULL it is also printed to the outputFile.
  651.  *    
  652.  * Results:
  653.  *    None.
  654.  *
  655.  * Side effects:
  656.  *    Stuff gets printed on the given stream and the output stream.
  657.  *
  658.  *----------------------------------------------------------------------
  659.  */
  660.  
  661. #ifndef lint
  662.  
  663. int
  664. Output(va_alist)
  665.     va_dcl            /* FILE *stream, then char *format, then any
  666.                  * number of additional
  667.                  * values to be printed as described by                         * format. */
  668. {
  669.     FILE *stream;
  670.     char *format;
  671.     va_list args;
  672.     static bufferFull = FALSE;
  673.     extern char *deviceName;
  674.     extern char *partName;
  675.     int    status;
  676.  
  677.     va_start(args);
  678.     stream = va_arg(args, FILE *);
  679.     format = va_arg(args, char *);
  680.     if ((!bufferFull) && (outputFile != NULL)) {
  681.     if (fprintf(outputFile, "%s%s: ", deviceName, partName) == -1) {
  682.         bufferFull = TRUE;
  683.     }
  684.     if (bufferFull != TRUE) {
  685.         if (vfprintf(outputFile, format, args) == -1) {
  686.         bufferFull = TRUE;
  687.         }
  688.     }
  689.     }
  690.     status = fprintf(stream, "%s%s: ", deviceName, partName);
  691.     if (status != -1) {
  692.     status = vfprintf(stream, format, args);
  693.     }
  694.     return status;
  695. }
  696. #else
  697. /* VARARGS1 */
  698. /* ARGSUSED */
  699. int
  700. Output(stream,format)
  701.     FILE *stream;
  702.     char *format;
  703. {
  704.     return 0;
  705. }
  706. #endif lint
  707.  
  708.  
  709. /* 
  710.  *----------------------------------------------------------------------
  711.  *
  712.  * OutputPerror --
  713.  *
  714.  *    Prints the given message on stderr and the outputFile stream 
  715.  *    using the same format as OutputPerror().
  716.  *
  717.  * Results:
  718.  *    None.
  719.  *
  720.  * Side effects:
  721.  *    Stuff gets printed.
  722.  *
  723.  *----------------------------------------------------------------------
  724.  */
  725.  
  726. #ifndef lint
  727. void
  728. OutputPerror(va_alist)
  729.     va_dcl            /* char *format, then any
  730.                  * number of additional
  731.                  * values to be printed as described by                         * format. */
  732. {
  733.     char *format;
  734.     va_list args;
  735.  
  736.     va_start(args);
  737.     format = va_arg(args, char *);
  738.     if ((format != 0) && (*format != 0)) {
  739.     Output(stderr, format, args);
  740.     }
  741.     if ((errno < 0) || (errno >= sys_nerr)) {
  742.     return;
  743.     }
  744.     Output(stderr, "%s\n", sys_errlist[errno]);
  745. }
  746.  
  747. #else
  748. /* VARARGS1 */
  749. /* ARGSUSED */
  750. void 
  751. OutputPerror(msg)
  752.     char *msg;        
  753. {
  754. }
  755. #endif
  756.  
  757.  
  758.  
  759. /*
  760.  *----------------------------------------------------------------------
  761.  *
  762.  * WriteOutputFile ---
  763.  *    
  764.  *    This procedure is invoked when the outputFile stream buffer is full.
  765.  *      All we do here is set the status on the stream to -1, to indicate
  766.  *      that the buffer is full. The buffer is actually written out when the
  767.  *    stream is closed.
  768.  *    
  769.  * Results:
  770.  *    None.
  771.  *
  772.  * Side effects:
  773.  *    Status in FILE is set to -1.
  774.  *
  775.  *----------------------------------------------------------------------
  776.  */
  777.  
  778. /*ARGSUSED*/
  779. void
  780. WriteOutputFile(stream,flush)
  781.     FILE *stream;        /* pointer to outputFile */
  782.     int flush;             /* ignore this */
  783. {
  784.     if (!silent && stream->status != -1 && 
  785.         stream->lastAccess + 1 - stream->buffer == stream->bufSize) {
  786.     fprintf(stderr,">>Output buffer overflow. %s\n",
  787.             "Subsequent output will not appear in output file.");
  788.     }
  789.     stream->status = -1;
  790. }
  791.  
  792.  
  793. /*
  794.  *----------------------------------------------------------------------
  795.  *
  796.  * CloseOutputFile ---
  797.  *
  798.  *     Flushes the buffer to disk. 
  799.  *    
  800.  * Results:
  801.  *    None.
  802.  *
  803.  * Side effects:
  804.  *    None.
  805.  *
  806.  *----------------------------------------------------------------------
  807.  */
  808.  
  809. int
  810. CloseOutputFile(stream)
  811.     FILE *stream;        /* pointer to outputFile */
  812. {
  813.     Fsdm_FileDescriptor *fdPtr;
  814.     static u_char fdBlock[FS_BLOCK_SIZE];
  815.     static u_char buffer[FS_BLOCK_SIZE];
  816.     static u_char tempBuffer[10];
  817.     int         bytesToWrite;
  818.     int            bytesWritten;
  819.     int            blockNum;
  820.     int            offset;
  821.     int            startBlock;
  822.     int            startByte;
  823.     int            i;
  824.     int            bytesUsed;
  825.     int            bytesDone;
  826.  
  827.  
  828.     if (!writeDisk) {
  829.     return;
  830.     }
  831.     if (outputFileNum == -1) {
  832.     Output(stderr,
  833.         "File %s does not exist in root directory. %s\n",
  834.         outputFileName,
  835.         "Unable to write output to disk.");
  836.         return;
  837.     }
  838.     blockNum = domainPtr->fileDescOffset + 
  839.            outputFileNum / FSDM_FILE_DESC_PER_BLOCK;
  840.     offset = (outputFileNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) * 
  841.           FSDM_MAX_FILE_DESC_SIZE;
  842.     if (debug) {
  843.     Output(stderr,"Output file number is %d.\n", outputFileNum);
  844.     }
  845.     if (Disk_BlockRead(partFID, domainPtr, blockNum, 1, 
  846.                (Address) fdBlock) < 0) {
  847.     OutputPerror("Unable to read output fd.");
  848.     return;
  849.     }
  850.     fdPtr = (Fsdm_FileDescriptor *) &fdBlock[offset];
  851.     if (fdPtr->direct[0] != FSDM_NIL_INDEX) {
  852.     if (Disk_BlockRead(partFID, domainPtr,
  853.               VirtToPhys(domainPtr, fdPtr->direct[0]) /
  854.               FS_FRAGMENTS_PER_BLOCK, 1,
  855.               (Address) buffer) < 0) {
  856.         Output(stderr,"Can't read output file.");
  857.         return;
  858.     }
  859.     if (sscanf(buffer," %d",&bytesUsed) != 1) {
  860.         bytesUsed = 0;
  861.     }
  862.     } else {
  863.     bytesUsed = 0;
  864.     }
  865.     if (fdPtr->lastByte + 1 - bytesUsed  < 
  866.     stream->bufSize - stream->writeCount) {
  867.     Output(stderr,
  868.         "Output file %s is not big enough for all the output, %d > %d\n",
  869.            outputFileName, stream->bufSize - stream->writeCount, 
  870.            fdPtr->lastByte + 1 - bytesUsed);
  871.     bytesToWrite = fdPtr->lastByte + 1 - bytesUsed;
  872.     } else {
  873.     bytesToWrite = stream->bufSize - stream->writeCount;
  874.     }
  875.     if (bytesUsed + bytesToWrite > FSDM_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE) {
  876.     Output(stderr,"Output exceeds direct blocks in file.\n");
  877.     bytesToWrite = FSDM_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE - bytesUsed;
  878.     }
  879.     if (debug) {
  880.     Output(stderr,"There are %d bytes of output to be written.\n",
  881.            bytesToWrite);
  882.     }
  883.     startBlock = bytesUsed / FS_BLOCK_SIZE;
  884.     startByte = bytesUsed - startBlock * FS_BLOCK_SIZE;
  885.     bytesDone = bytesUsed;
  886.  
  887.     for (i = startBlock, bytesWritten = 0; 
  888.      bytesDone <= fdPtr->lastByte && 
  889.      i < FSDM_NUM_DIRECT_BLOCKS; 
  890.      i++) {
  891.     if (fdPtr->direct[i] == FSDM_NIL_INDEX) {
  892.         Output(stderr,"Output file has a hole -- you lose.\n");
  893.         continue;
  894.     }
  895.     if (debug) {
  896.         Output(stderr,"Writing to block %d.\n",fdPtr->direct[i]);
  897.     }
  898.     if (startByte > 0 || 
  899.         bytesToWrite - bytesWritten < FS_BLOCK_SIZE - startByte) {
  900.         int numBytes;
  901.         int bytesToZero;
  902.  
  903.         numBytes = min(bytesToWrite - bytesWritten,
  904.                FS_BLOCK_SIZE - startByte);
  905.         if (Disk_BlockRead(partFID, domainPtr,
  906.               VirtToPhys(domainPtr, fdPtr->direct[i]) /
  907.               FS_FRAGMENTS_PER_BLOCK, 1,
  908.               (Address) buffer) < 0) {
  909.         Output(stderr,"Can't read output file.");
  910.         return;
  911.         }
  912.         bcopy((Address) &stream->buffer[bytesWritten],
  913.           (Address) &buffer[startByte], numBytes);
  914.         bytesToZero = min(fdPtr->lastByte + 1 - bytesDone - numBytes,
  915.                   FS_BLOCK_SIZE - startByte - numBytes);
  916.         bzero((Address) &buffer[startByte + numBytes], bytesToZero);
  917.         if (Disk_BlockWrite(partFID, domainPtr, 
  918.                    VirtToPhys(domainPtr,fdPtr->direct[i]) / 
  919.                    FS_FRAGMENTS_PER_BLOCK, 1, buffer)  < 0) {
  920.         OutputPerror("Unable to write to output file");
  921.         return;
  922.         }
  923.         bytesWritten += numBytes;
  924.         bytesDone += numBytes + bytesToZero;
  925.         startByte = 0;
  926.     } else {
  927.         if (Disk_BlockWrite(partFID, domainPtr, 
  928.                    VirtToPhys(domainPtr,fdPtr->direct[i]) / 
  929.                    FS_FRAGMENTS_PER_BLOCK, 1, 
  930.                    (Address) &stream->buffer[bytesWritten]) < 0) {
  931.         OutputPerror("Unable to write to output file");
  932.         return;
  933.         }
  934.         bytesWritten += FS_BLOCK_SIZE;
  935.         bytesDone += FS_BLOCK_SIZE;
  936.     }
  937.     }
  938.     if (fdPtr->direct[0] != FSDM_NIL_INDEX) {
  939.     if (Disk_BlockRead(partFID, domainPtr,
  940.               VirtToPhys(domainPtr, fdPtr->direct[0]) /
  941.               FS_FRAGMENTS_PER_BLOCK, 1,
  942.               (Address) buffer) < 0) {
  943.         Output(stderr,"Can't read output file.");
  944.         return;
  945.     }
  946.     sprintf(tempBuffer,"%05d",bytesWritten + bytesUsed);
  947.     bcopy(tempBuffer, buffer, 5);
  948.     if (Disk_BlockWrite(partFID, domainPtr,
  949.               VirtToPhys(domainPtr, fdPtr->direct[0]) /
  950.               FS_FRAGMENTS_PER_BLOCK, 1,
  951.               (Address) buffer) < 0) {
  952.         Output(stderr,"Can't write output file.");
  953.         return;
  954.     }
  955.     }
  956. }
  957.  
  958.  
  959. /*
  960.  *----------------------------------------------------------------------
  961.  *
  962.  * ExitHandler ---
  963.  *
  964.  *     Called when program exits. Flushes output stream.
  965.  *    
  966.  * Results:
  967.  *    None.
  968.  *
  969.  * Side effects:
  970.  *    None.
  971.  *
  972.  *----------------------------------------------------------------------
  973.  */
  974.  
  975. void
  976. ExitHandler()
  977. {
  978.     if (outputFile != NULL && rawOutput) {
  979.     CloseOutputFile(outputFile);
  980.     }
  981. }
  982.  
  983. /*
  984.  *----------------------------------------------------------------------
  985.  *
  986.  * ClearFd ---
  987.  *
  988.  *     Clears the contents of the fd.
  989.  *    
  990.  * Results:
  991.  *    None.
  992.  *
  993.  * Side effects:
  994.  *    None.
  995.  *
  996.  *----------------------------------------------------------------------
  997.  */
  998.  
  999. void
  1000. ClearFd(flags, fdPtr)
  1001.     int    flags;                /* File descriptor flags */ 
  1002.     Fsdm_FileDescriptor *fdPtr;        /* File descriptor to be cleared */
  1003. {
  1004.     int index;
  1005.  
  1006.     fdPtr->magic = FSDM_FD_MAGIC;
  1007.     fdPtr->flags = flags;
  1008.     fdPtr->firstByte = -1;
  1009.     fdPtr->lastByte = -1;
  1010.     fdPtr->numKbytes = 0;
  1011.     fdPtr->fileType = FS_FILE;
  1012.     fdPtr->uid = 0;
  1013.     fdPtr->gid = 0;
  1014.     fdPtr->numLinks = 0;
  1015.     for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  1016.     fdPtr->direct[index] = FSDM_NIL_INDEX;
  1017.     }
  1018.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  1019.     fdPtr->indirect[index] = FSDM_NIL_INDEX;
  1020.     }
  1021. }
  1022.  
  1023. /*
  1024.  * A table indexed by a 4 bit value is used by the allocation routine to 
  1025.  * quickly determine the location of 1, 2, and 3K fragments in a byte.  
  1026.  * The indices of the fragments start from 0.  If there is no such fragment in 
  1027.  * the byte then a -1 is used.
  1028.  */
  1029.  
  1030. static int fragTable[16][3] = {
  1031. /* 0000 */ {-1, -1, -1},
  1032. /* 0001 */ {-1, -1, 0},
  1033. /* 0010 */ {3, 0, -1},
  1034. /* 0011 */ {-1, 0, -1},
  1035. /* 0100 */ {0, 2, -1},
  1036. /* 0101 */ {0, -1, -1},
  1037. /* 0110 */ {0, -1, -1},
  1038. /* 0111 */ {0, -1, -1},
  1039. /* 1000 */ {-1, -1, 1},
  1040. /* 1001 */ {-1, 1, -1},
  1041. /* 1010 */ {1, -1, -1},
  1042. /* 1011 */ {1, -1, -1},
  1043. /* 1100 */ {-1, 2, -1},
  1044. /* 1101 */ {2, -1, -1},
  1045. /* 1110 */ {3, -1, -1},
  1046. /* 1111 */ {-1, -1, -1}
  1047. };
  1048. /*
  1049.  * Macros to get to the 4-bit fragment masks of the two 4K blocks that are 
  1050.  * stored in a byte.
  1051.  */
  1052.  
  1053. #define    UpperBlockFree(byte)    (((byte) & 0xf0) == 0x00)
  1054. #define    LowerBlockFree(byte)    (((byte) & 0x0f) == 0x00)
  1055. #define    BothBlocksFree(byte)    (((byte) & 0xff) == 0x00)
  1056. #define    GetUpperFragMask(byte) (((byte) >> 4) & 0x0f)
  1057. #define    GetLowerFragMask(byte) ((byte) & 0x0f)
  1058.  
  1059. /*
  1060.  *----------------------------------------------------------------------
  1061.  *
  1062.  * AllocBlock --
  1063.  *
  1064.  *    Allocates free fragments.
  1065.  *
  1066.  * Results:
  1067.  *    -1 if a free block cannot be found, 
  1068.  *    the virtual block number of the free block otherwise
  1069.  *
  1070.  * Side effects:
  1071.  *    Marks the fragments as allocated in the bitmap
  1072.  *
  1073.  *----------------------------------------------------------------------
  1074.  */
  1075.  
  1076. int
  1077. AllocBlock(domainPtr, fragments, blockBitmapPtr)
  1078.     Ofs_DomainHeader     *domainPtr;         /* Ptr at domain info */
  1079.     int            fragments;        /* Number of fragments needed */
  1080.     u_char        *blockBitmapPtr;    /* Cylinder data block bitmap */
  1081. {
  1082.     int     mask;
  1083.     int     i;
  1084.     int        j;
  1085.     int     blocksPerCylinder;
  1086.     int        bitmapBytes;
  1087.     int     offset;
  1088.     int        fragSize;
  1089.     u_char    *bitmapPtr;
  1090.  
  1091.     if (fragments < 1 || fragments > FS_FRAGMENTS_PER_BLOCK) {
  1092.     Output(stderr,"Internal error: call to AllocBlock w/ fragments = %d\n",
  1093.            fragments);
  1094.         exit(EXIT_HARD_ERROR);
  1095.     }
  1096.     blocksPerCylinder = domainPtr->geometry.blocksPerCylinder;
  1097.     bitmapBytes = (unsigned int) (blocksPerCylinder + 1) / 2;
  1098.     mask = ((1 << fragments) - 1);
  1099.     fragSize = fragments;
  1100.  
  1101.     /*
  1102.      * Look for fragment of correct size, then size +1, size +2, etc.
  1103.      */
  1104.     while (fragSize <= FS_FRAGMENTS_PER_BLOCK) {
  1105.     for (i = 0, bitmapPtr = blockBitmapPtr; 
  1106.          i < domainPtr->dataCylinders; 
  1107.          i++) {
  1108.  
  1109.         for (j = 0; j < bitmapBytes; j++, bitmapPtr++) {
  1110.         /*
  1111.          * Block 0 belongs to the root directory so don't allocate it 
  1112.          * even if it is free.
  1113.          */
  1114.         if (j + i != 0) {
  1115.             if (fragSize == 4) {
  1116.             if (UpperBlockFree(*bitmapPtr)) {
  1117.                 mask <<= FS_FRAGMENTS_PER_BLOCK - fragments;
  1118.                 *bitmapPtr |= mask << 4;
  1119.                 return (i * blocksPerCylinder + j * 2) * 
  1120.                     FS_FRAGMENTS_PER_BLOCK; 
  1121.             }
  1122.             } else {
  1123.             offset = 
  1124.                 fragTable[GetUpperFragMask(*bitmapPtr)][fragSize-1];
  1125.             if (offset > -1) {
  1126.                 mask <<= FS_FRAGMENTS_PER_BLOCK - offset - 
  1127.                      fragments;
  1128.                 *bitmapPtr |= mask << 4;
  1129.                 return (i * blocksPerCylinder + j * 2) * 
  1130.                     FS_FRAGMENTS_PER_BLOCK + offset; 
  1131.             }
  1132.             }
  1133.         }
  1134.         /*
  1135.          * There may be an odd number of blocks per cylinder.  If so
  1136.          * and are at the end of the bit map for this cylinder, then
  1137.          * we can bail out now.
  1138.          */
  1139.     
  1140.         if (j == (bitmapBytes - 1) && (blocksPerCylinder & 0x1)) {
  1141.             continue;
  1142.         }
  1143.         if (fragSize == 4) {
  1144.             if (LowerBlockFree(*bitmapPtr)) {
  1145.             mask <<= FS_FRAGMENTS_PER_BLOCK - fragments;
  1146.             *bitmapPtr |= mask;
  1147.             return (i * blocksPerCylinder + j * 2 + 1) * 
  1148.                 FS_FRAGMENTS_PER_BLOCK; 
  1149.             }
  1150.         } else {
  1151.             offset = 
  1152.             fragTable[GetLowerFragMask(*bitmapPtr)][fragSize-1];
  1153.             if (offset > -1) {
  1154.             mask <<= FS_FRAGMENTS_PER_BLOCK - offset - fragments;
  1155.             *bitmapPtr |= mask;
  1156.             return (i * blocksPerCylinder + j * 2 + 1) * 
  1157.                 FS_FRAGMENTS_PER_BLOCK + offset; 
  1158.             }
  1159.         }
  1160.         }
  1161.     }
  1162.     fragSize++;
  1163.     }
  1164.     /*
  1165.      * Disk is full
  1166.      */
  1167.     return -1;
  1168. }
  1169.  
  1170.  
  1171. /*
  1172.  *----------------------------------------------------------------------
  1173.  *
  1174.  * AddToCopyList --
  1175.  *
  1176.  *    Adds information about the block to be copied to the copy list.
  1177.  *
  1178.  * Results:
  1179.  *    None.
  1180.  *
  1181.  * Side effects:
  1182.  *    Copy list element is malloced, added to copy list.
  1183.  *
  1184.  *----------------------------------------------------------------------
  1185.  */
  1186.  
  1187. void
  1188. AddToCopyList(parentType,fdPtr, fdNum, blockNum, index, blockType,fragments,
  1189.           copyUsedPtr)
  1190.     ParentType        parentType;     /* either a fd or an indirect block */
  1191.     Fsdm_FileDescriptor    *fdPtr;        /* ptr to parent fd */
  1192.     int            fdNum;        /* number of parent fd */
  1193.     int            blockNum;    /* number of parent block */
  1194.     int            index;        /* index of pointer  in parent */
  1195.     BlockIndexType    blockType;    /* type of block being copied */
  1196.     int            fragments;    /* number of fragments to copy*/
  1197.     Boolean        *copyUsedPtr;    /* Was copy of fd used ? */
  1198. {
  1199.     CopyListElement    *copyPtr;
  1200.  
  1201.     Alloc(copyPtr,CopyListElement,1);
  1202.     if (!tooBig) {
  1203.     List_InitElement((List_Links *) copyPtr);
  1204.     copyPtr->fdPtr = fdPtr;
  1205.     copyPtr->parentType = parentType;
  1206.     if (parentType == FD) {
  1207.         copyPtr->parentNum = fdNum;
  1208.         *copyUsedPtr = TRUE;
  1209.     } else {
  1210.         copyPtr->parentNum = blockNum;
  1211.     }
  1212.     copyPtr->index = index;
  1213.     copyPtr->blockType = blockType;
  1214.     copyPtr->fragments = fragments;
  1215.     List_Insert((List_Links *) copyPtr,
  1216.             LIST_ATREAR(copyList));
  1217.     }
  1218. }
  1219.  
  1220.  
  1221. /*
  1222.  *----------------------------------------------------------------------
  1223.  *
  1224.  * FindOutputFile --
  1225.  *
  1226.  *    Finds the output file for raw output.  This routine should only
  1227.  *    be called if the disk has been checked previously, since the
  1228.  *    output file will be found in CheckDirTree otherwise.
  1229.  *    
  1230.  *
  1231.  * Results:
  1232.  *    None.
  1233.  *
  1234.  * Side effects:
  1235.  *    None.
  1236.  *
  1237.  *----------------------------------------------------------------------
  1238.  */
  1239.  
  1240. void
  1241. FindOutputFile()
  1242. {
  1243.     Fsdm_FileDescriptor    *rootFDPtr;
  1244.     FdInfo        fdInfo;
  1245.     DirIndexInfo    dirIndex;
  1246.     Fslcl_DirEntry    *dirEntryPtr;
  1247.     int            length;
  1248.     int            blockNum;
  1249.     int            offset;
  1250.     static char        block[FS_BLOCK_SIZE];
  1251.     extern void        OpenDir();
  1252.     extern void        NextDirEntry();
  1253.  
  1254.  
  1255.     if (!rawOutput) {
  1256.     return;
  1257.     }
  1258.     if (outputFileName == NULL) {
  1259.     return;
  1260.     }
  1261.     length = strlen(outputFileName);
  1262.     blockNum = domainPtr->fileDescOffset + 
  1263.             FSDM_ROOT_FILE_NUMBER / FSDM_FILE_DESC_PER_BLOCK;
  1264.     offset = (FSDM_ROOT_FILE_NUMBER & (FSDM_FILE_DESC_PER_BLOCK - 1)) * 
  1265.         FSDM_MAX_FILE_DESC_SIZE;
  1266.     if (Disk_BlockRead(partFID, domainPtr, blockNum, 1, 
  1267.                (Address) block) < 0) {
  1268.        return;
  1269.     }
  1270.     rootFDPtr = (Fsdm_FileDescriptor *) &block[offset];
  1271.     OpenDir(rootFDPtr, &fdInfo, &dirIndex, &dirEntryPtr);
  1272.     while (dirEntryPtr != (Fslcl_DirEntry *) NULL) {
  1273.     if ((dirEntryPtr->nameLength == length) &&
  1274.         (strncmp(outputFileName, dirEntryPtr->fileName, length) == 0)) {
  1275.  
  1276.         outputFileNum = dirEntryPtr->fileNumber;
  1277.         return;
  1278.     }
  1279.     NextDirEntry(&dirIndex, &dirEntryPtr);
  1280.     }
  1281. }
  1282.  
  1283. @
  1284.  
  1285.  
  1286. 1.9
  1287. log
  1288. @puts output in .fscheck.out even if disk already checked, updated ot
  1289. ofs
  1290. @
  1291. text
  1292. @d17 1
  1293. a17 1
  1294. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fsUtils.c,v 1.8 90/10/10 15:29:09 mendel Exp $ SPRITE (Berkeley)";
  1295. d29 1
  1296. d324 1
  1297. d348 1
  1298. d355 1
  1299. d364 4
  1300. a367 1
  1301.         if (!strcmp(serverInfoPtr->name, getenv("HOST"))) {
  1302. @
  1303.  
  1304.  
  1305. 1.8
  1306. log
  1307. @Changes to reflect new OFS file system names.
  1308. @
  1309. text
  1310. @d17 1
  1311. a17 1
  1312. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fsUtils.c,v 1.7 90/10/10 11:22:15 jhh Exp Locker: mendel $ SPRITE (Berkeley)";
  1313. a355 2
  1314.         printf("server of prefix %s is %d\n", prefix.prefix, 
  1315.             prefix.serverID);
  1316. a357 2
  1317.             printf("Can't get server info for server %d\n",
  1318.             prefix.serverID);
  1319. d1144 62
  1320. @
  1321.  
  1322.  
  1323. 1.7
  1324. log
  1325. @now can do raw output on any partition, fixed bug with ".."
  1326. @
  1327. text
  1328. @d17 1
  1329. a17 1
  1330. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fsUtils.c,v 1.6 90/05/01 15:36:47 jhh Exp $ SPRITE (Berkeley)";
  1331. d55 1
  1332. a55 1
  1333.     register Fsdm_DomainHeader *domainPtr;    /* Ptr to domain to read bitmap for. */
  1334. d94 1
  1335. a94 1
  1336.     register Fsdm_DomainHeader     *domainPtr;    /* Domain to write bitmap for.*/
  1337. d123 1
  1338. a123 1
  1339.     register Fsdm_DomainHeader    *domainPtr;    /* Domain to read. */
  1340. d158 1
  1341. a158 1
  1342.     register Fsdm_DomainHeader    *domainPtr;    /* Domain to write. */
  1343. d187 1
  1344. a187 1
  1345.     register Fsdm_DomainHeader     *domainPtr;    /* Domain to write to. */
  1346. d256 1
  1347. a256 1
  1348.     Fsdm_DomainHeader    *domainPtr;    /* Reference to domain header to
  1349. d261 1
  1350. a261 1
  1351.     Fsdm_SummaryInfo    *summaryInfoPtr;
  1352. d285 1
  1353. a285 1
  1354.         "Setting FSDM_DOMAIN_JUST_CHECKED bit in summary sector.\n");
  1355. d287 1
  1356. a287 1
  1357.     summaryInfoPtr->flags |= FSDM_DOMAIN_JUST_CHECKED;
  1358. d320 1
  1359. a320 1
  1360.     Fsdm_SummaryInfo        *summaryInfoPtr;
  1361. d334 1
  1362. a334 1
  1363.            (summaryInfoPtr->flags & FSDM_DOMAIN_NOT_SAFE) ? "not-safe" : 
  1364. d336 1
  1365. a336 1
  1366.         if (summaryInfoPtr->flags & FSDM_DOMAIN_TIMES_VALID) {
  1367. d377 1
  1368. a377 1
  1369.     return(summaryInfoPtr->flags & FSDM_DOMAIN_JUST_CHECKED);
  1370. d402 1
  1371. a402 1
  1372.     register    Fsdm_DomainHeader     *domainPtr;        /* Domain to check. */
  1373. d467 1
  1374. a467 1
  1375.     register    Fsdm_DomainHeader     *domainPtr;        /* Domain to fix. */
  1376. d509 1
  1377. a509 1
  1378.     Fsdm_DomainHeader  *domainPtr;
  1379. d1006 1
  1380. a1006 1
  1381.     Fsdm_DomainHeader     *domainPtr;         /* Ptr at domain info */
  1382. @
  1383.  
  1384.  
  1385. 1.6
  1386. log
  1387. @ported to new Disk library
  1388. @
  1389. text
  1390. @d17 1
  1391. a17 1
  1392. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/fsUtils.c,v 1.5 90/02/14 15:55:33 jhh Exp $ SPRITE (Berkeley)";
  1393. d28 1
  1394. d321 2
  1395. d346 25
  1396. d906 1
  1397. a906 1
  1398.     if (outputFile != NULL && rootPart) {
  1399. @
  1400.  
  1401.  
  1402. 1.5
  1403. log
  1404. @support for no recheck on reboot
  1405. @
  1406. text
  1407. @d17 1
  1408. a17 1
  1409. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fsUtils.c,v 1.4 89/10/03 17:47:50 jhh Exp $ SPRITE (Berkeley)";
  1410. a21 1
  1411. #include "diskUtils.h"
  1412. a34 59
  1413.  
  1414. /*
  1415.  *----------------------------------------------------------------------
  1416.  *
  1417.  * ReadDomainHeader --
  1418.  *
  1419.  *    Read the domain header off the disk.
  1420.  *
  1421.  * Results:
  1422.  *    None.
  1423.  *
  1424.  * Side effects:
  1425.  *    Fill in the domain header.
  1426.  *
  1427.  *----------------------------------------------------------------------
  1428.  */
  1429. void
  1430. ReadDomainHeader(partFID, diskInfoPtr, domainPtr)
  1431.     int            partFID;    /* Handle on raw disk */
  1432.     Disk_Info        *diskInfoPtr;    /* Information from the super block */
  1433.     Fsdm_DomainHeader    *domainPtr;    /* Reference to domain header to
  1434.                      * fill in */
  1435. {
  1436.     if (Disk_SectorRead(partFID, diskInfoPtr->domainSector,
  1437.            diskInfoPtr->numDomainSectors, (Address)domainPtr) < 0) {
  1438.     OutputPerror("ReadDomainHeader: Read failed");
  1439.     exit(EXIT_READ_FAILURE);
  1440.     }
  1441. }
  1442.  
  1443.  
  1444. /*
  1445.  *----------------------------------------------------------------------
  1446.  *
  1447.  * WriteDomainHeader --
  1448.  *
  1449.  *    Read the domain header off the disk.
  1450.  *
  1451.  * Results:
  1452.  *    None.
  1453.  *
  1454.  * Side effects:
  1455.  *    Fill in the domain header.
  1456.  *
  1457.  *----------------------------------------------------------------------
  1458.  */
  1459. void
  1460. WriteDomainHeader(partFID, diskInfoPtr, domainPtr)
  1461.     int            partFID;    /* Handle on raw disk */
  1462.     Disk_Info        *diskInfoPtr;    /* Information from the super block */
  1463.     Fsdm_DomainHeader    *domainPtr;    /* Reference to domain header to
  1464.                      * fill in */
  1465. {
  1466.     if (Disk_SectorWrite(partFID, diskInfoPtr->domainSector,
  1467.             diskInfoPtr->numDomainSectors, (Address)domainPtr) < 0) {
  1468.     OutputPerror("WriteDomainHeader: Write failed");
  1469.     exit(EXIT_WRITE_FAILURE);
  1470.     }
  1471. }
  1472. d252 1
  1473. a252 1
  1474. WriteSummaryInfo(partFID, diskInfoPtr, domainPtr, numKblocks, numFiles)
  1475. d254 1
  1476. a254 1
  1477.     Disk_Info        *diskInfoPtr;    /* Information from the super block */
  1478. d263 1
  1479. a263 1
  1480.     summaryInfoPtr = Disk_ReadSummaryInfo(partFID, diskInfoPtr);
  1481. d289 1
  1482. a289 1
  1483.     status = Disk_WriteSummaryInfo(partFID, diskInfoPtr, summaryInfoPtr);
  1484. d315 1
  1485. a315 1
  1486. RecoveryCheck(partFID, diskInfoPtr)
  1487. d317 1
  1488. a317 1
  1489.     Disk_Info        *diskInfoPtr;    /* Information from the super block */
  1490. d321 1
  1491. a321 1
  1492.     summaryInfoPtr = Disk_ReadSummaryInfo(partFID, diskInfoPtr);
  1493. @
  1494.  
  1495.  
  1496. 1.4
  1497. log
  1498. @added device prefix to all output lines
  1499. @
  1500. text
  1501. @d17 1
  1502. a17 1
  1503. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fsUtils.c,v 1.3 89/09/25 16:41:21 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  1504. a319 1
  1505.     char        buffer[DEV_BYTES_PER_SECTOR];
  1506. d321 1
  1507. d323 2
  1508. a324 1
  1509.     if (Disk_SectorRead(partFID, diskInfoPtr->summarySector, 1, buffer) < 0) {
  1510. a327 1
  1511.     summaryInfoPtr = (Fsdm_SummaryInfo *) buffer;
  1512. d336 12
  1513. a347 1
  1514.     summaryInfoPtr->flags = 0;
  1515. d349 2
  1516. a350 1
  1517.     if (Disk_SectorWrite(partFID, diskInfoPtr->summarySector, 1, buffer) < 0) {
  1518. d354 1
  1519. a354 1
  1520.  
  1521. d363 1
  1522. a363 1
  1523.  *    See if the disk was successfully synced. Print out information
  1524. d367 1
  1525. a367 1
  1526.  *    Return 1 if the disk not safely synced.
  1527. a378 1
  1528.     char            buffer[DEV_BYTES_PER_SECTOR];
  1529. d381 3
  1530. a383 2
  1531.     if (Disk_SectorRead(partFID, diskInfoPtr->summarySector, 1, buffer) < 0) {
  1532.     OutputPerror("RecoveryCheck: Summary sector read failed");
  1533. a385 1
  1534.     summaryInfoPtr = (Fsdm_SummaryInfo *)buffer;
  1535. d400 2
  1536. d409 1
  1537. a409 1
  1538.     return(summaryInfoPtr->flags & FSDM_DOMAIN_NOT_SAFE);
  1539. @
  1540.  
  1541.  
  1542. 1.3
  1543. log
  1544. @Uses new fs module structure
  1545. @
  1546. text
  1547. @d17 1
  1548. a17 1
  1549. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fsUtils.c,v 1.2 89/06/21 23:56:14 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  1550. d620 3
  1551. d628 1
  1552. a628 1
  1553.     if (vfprintf(outputFile, format, args) == -1) {
  1554. d631 9
  1555. d641 1
  1556. a641 1
  1557.     return vfprintf(stream, format, args);
  1558. @
  1559.  
  1560.  
  1561. 1.2
  1562. log
  1563. @Various bug fixes
  1564. @
  1565. text
  1566. @d17 1
  1567. a17 1
  1568. static char rcsid[] = "$Header: /a/newcmds/fscheck/RCS/fsUtils.c,v 1.1 89/02/28 12:23:51 jhh Exp $ SPRITE (Berkeley)";
  1569. d56 1
  1570. a56 1
  1571.     FsDomainHeader    *domainPtr;    /* Reference to domain header to
  1572. d86 1
  1573. a86 1
  1574.     FsDomainHeader    *domainPtr;    /* Reference to domain header to
  1575. d114 1
  1576. a114 1
  1577.     register FsDomainHeader *domainPtr;    /* Ptr to domain to read bitmap for. */
  1578. d153 1
  1579. a153 1
  1580.     register FsDomainHeader     *domainPtr;    /* Domain to write bitmap for.*/
  1581. d182 1
  1582. a182 1
  1583.     register FsDomainHeader    *domainPtr;    /* Domain to read. */
  1584. d217 1
  1585. a217 1
  1586.     register FsDomainHeader    *domainPtr;    /* Domain to write. */
  1587. d246 1
  1588. a246 1
  1589.     register FsDomainHeader     *domainPtr;    /* Domain to write to. */
  1590. d263 3
  1591. a265 3
  1592.             modElemPtr->fdNum / FS_FILE_DESC_PER_BLOCK;
  1593.     offset = (modElemPtr->fdNum & (FS_FILE_DESC_PER_BLOCK - 1)) *
  1594.             FS_MAX_FILE_DESC_SIZE;
  1595. d286 1
  1596. a286 1
  1597.           sizeof(FsFileDescriptor));
  1598. d315 1
  1599. a315 1
  1600.     FsDomainHeader    *domainPtr;    /* Reference to domain header to
  1601. d321 1
  1602. a321 1
  1603.     FsSummaryInfo    *summaryInfoPtr;
  1604. d327 1
  1605. a327 1
  1606.     summaryInfoPtr = (FsSummaryInfo *) buffer;
  1607. d368 1
  1608. a368 1
  1609.     FsSummaryInfo        *summaryInfoPtr;
  1610. d374 1
  1611. a374 1
  1612.     summaryInfoPtr = (FsSummaryInfo *)buffer;
  1613. d380 1
  1614. a380 1
  1615.            (summaryInfoPtr->flags & FS_DOMAIN_NOT_SAFE) ? "not-safe" : 
  1616. d382 1
  1617. a382 1
  1618.         if (summaryInfoPtr->flags & FS_DOMAIN_TIMES_VALID) {
  1619. d396 1
  1620. a396 1
  1621.     return(summaryInfoPtr->flags & FS_DOMAIN_NOT_SAFE);
  1622. d421 1
  1623. a421 1
  1624.     register    FsDomainHeader     *domainPtr;        /* Domain to check. */
  1625. d432 1
  1626. a432 1
  1627.     FsFileDescriptor        *fdPtr;
  1628. d435 1
  1629. a435 1
  1630.      i < FS_FILE_DESC_PER_BLOCK / BITS_PER_BYTE && 
  1631. d442 1
  1632. a442 1
  1633.         fdPtr = (FsFileDescriptor *)&block[(i * BITS_PER_BYTE + j) * FS_MAX_FILE_DESC_SIZE];
  1634. d444 1
  1635. a444 1
  1636.         if (allocated && (fdPtr->flags & FS_FD_FREE)) {
  1637. d453 1
  1638. a453 1
  1639.         } else if (!allocated && !(fdPtr->flags & FS_FD_FREE)) {
  1640. d486 1
  1641. a486 1
  1642.     register    FsDomainHeader     *domainPtr;        /* Domain to fix. */
  1643. d494 1
  1644. a494 1
  1645.     for (i = 0; i < FS_FILE_DESC_PER_BLOCK / BITS_PER_BYTE && 
  1646. d528 1
  1647. a528 1
  1648.     FsDomainHeader  *domainPtr;
  1649. d559 1
  1650. a559 1
  1651.         (fdNum != FS_ROOT_FILE_NUMBER) && blockNum == 0) { 
  1652. d748 1
  1653. a748 1
  1654.     FsFileDescriptor *fdPtr;
  1655. d774 3
  1656. a776 3
  1657.            outputFileNum / FS_FILE_DESC_PER_BLOCK;
  1658.     offset = (outputFileNum & (FS_FILE_DESC_PER_BLOCK - 1)) * 
  1659.           FS_MAX_FILE_DESC_SIZE;
  1660. d785 2
  1661. a786 2
  1662.     fdPtr = (FsFileDescriptor *) &fdBlock[offset];
  1663.     if (fdPtr->direct[0] != FS_NIL_INDEX) {
  1664. d810 1
  1665. a810 1
  1666.     if (bytesUsed + bytesToWrite > FS_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE) {
  1667. d812 1
  1668. a812 1
  1669.     bytesToWrite = FS_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE - bytesUsed;
  1670. d824 1
  1671. a824 1
  1672.      i < FS_NUM_DIRECT_BLOCKS; 
  1673. d826 1
  1674. a826 1
  1675.     if (fdPtr->direct[i] == FS_NIL_INDEX) {
  1676. d873 1
  1677. a873 1
  1678.     if (fdPtr->direct[0] != FS_NIL_INDEX) {
  1679. d937 1
  1680. a937 1
  1681.     FsFileDescriptor *fdPtr;        /* File descriptor to be cleared */
  1682. d941 1
  1683. a941 1
  1684.     fdPtr->magic = FS_FD_MAGIC;
  1685. d950 2
  1686. a951 2
  1687.     for (index = 0; index < FS_NUM_DIRECT_BLOCKS ; index++) {
  1688.     fdPtr->direct[index] = FS_NIL_INDEX;
  1689. d953 2
  1690. a954 2
  1691.     for (index = 0; index < FS_NUM_INDIRECT_BLOCKS ; index++) {
  1692.     fdPtr->indirect[index] = FS_NIL_INDEX;
  1693. d1013 1
  1694. a1013 1
  1695.     FsDomainHeader     *domainPtr;         /* Ptr at domain info */
  1696. d1126 1
  1697. a1126 1
  1698.     FsFileDescriptor    *fdPtr;        /* ptr to parent fd */
  1699. @
  1700.  
  1701.  
  1702. 1.1
  1703. log
  1704. @Converted to new C library, added lots of new functionality
  1705. @
  1706. text
  1707. @d17 1
  1708. a17 1
  1709. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.2 89/01/07 04:12:18 rab Exp $ SPRITE (Berkeley)";
  1710. d337 1
  1711. d351 2
  1712. a352 1
  1713.  *    See if the disk was successfully synced.
  1714. d358 1
  1715. a358 1
  1716.  *    None.
  1717. d375 21
  1718. d445 1
  1719. a445 1
  1720.         if (verbose) {
  1721. d454 1
  1722. a454 1
  1723.         if (verbose) {
  1724. d719 2
  1725. a720 1
  1726.     if (!silent && stream->status != -1) {
  1727. d763 3
  1728. d802 4
  1729. a805 2
  1730.     Output(stderr,"Output file %s is not big enough for all the output.\n ",
  1731.            outputFileName);
  1732. @
  1733.